package sql.db;

import sql.exception.*;

public class Condition {
	
	private int op;
	private Predicate pred = null;
	private Condition left = null, right = null;
	
	private final int OR = 0;
	private final int AND = 1;
	private final int NOT = 2;
	private final int PRED = 3;

	public Condition(String op, Condition left, Condition right) {
		super();
		setOp(op);
		setLeft(left);
		setRight(right);
	}
	
	public Condition(String notOp, Condition cond) {
		super();
		setOp(notOp);
		setLeft(cond);
		setRight(null);
	}
	
	public Condition(Predicate pred) {
		super();
		setPred(pred);
		setOp("pred");
	}
	
	public int eval(Tuple tuple) throws MyDBException, Exception
	{
		if (op == PRED)
			return pred.eval(tuple);
		
		if (op == NOT) {
			switch (left.eval(tuple)) {
			case Main.TRUE: return Main.FALSE;
			case Main.FALSE: return Main.TRUE;
			case Main.UNKNOWN: return Main.UNKNOWN;
			}
		}
		
		int leftRes = left.eval(tuple);
		int rightRes = right.eval(tuple);
		
		if (op == OR) {
			if (leftRes == Main.TRUE || rightRes == Main.TRUE)
				return Main.TRUE;
			else if (leftRes == Main.UNKNOWN || rightRes == Main.UNKNOWN)
				return Main.UNKNOWN;
			else
				return Main.FALSE;
		}
		else if (op == AND) {
			if (leftRes == Main.FALSE || rightRes == Main.FALSE)
				return Main.FALSE;
			else if (leftRes == Main.UNKNOWN || rightRes == Main.UNKNOWN)
				return Main.UNKNOWN;
			else
				return Main.TRUE;
		}

		return Main.UNKNOWN; //unreachable line
	}
	
///////////////////////////////////////////////////////
	public String getOp() {
		if (op == OR)
			return new String("or");
		else if (op == AND)
			return new String("and");
		else if (op == NOT)
			return new String("not");
		else
			return new String("pred");
	}

	public void setOp(String op) {
		if (op.equals("or"))
			this.op = OR;
		else if (op.equals("and"))
			this.op = AND;
		else if (op.equals("not"))
			this.op = NOT;
		else
			this.op = PRED;
	}

	public Predicate getPred() {
		return pred;
	}

	public void setPred(Predicate pred) {
		this.pred = pred;
	}

	public Condition getLeft() {
		return left;
	}

	public void setLeft(Condition left) {
		this.left = left;
	}

	public Condition getRight() {
		return right;
	}

	public void setRight(Condition right) {
		this.right = right;
	}

}
